public static Bitmap applyKernel(int[] src, int w, int h, int[][] kernel) {
	Bitmap dst = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
	int kmw = (kernel[0].length - 1) / 2; // kernel mean width
	int kmh = (kernel.length - 1) / 2; // kernel mean height
	int r, g, b;
	// calculate new picture without border
		for (int y = kernel.length; y < (h - kernel.length); y++) {
			// set pixel at pos. y
			for (int x = kernel[0].length; x < (w - kernel[0].length); x++) {
				// set pixel at pos. x
				// read neighbor and calculate new pixel
				r = 0;g = 0;b = 0;
				for (int j = (y - kmh), ky = 0; j < (y + kmh + 1); j++, ky++) {
					for (int i = (x - kmw), kx = 0; i < (x + kmw + 1); i++, kx++) {
						int k = kernel[kx][ky]; // weight kernel
						r += (src[(j*w+i)*3+0] * k); // red
						g += (src[(j*w+i)*3+1] * k); // green
						b += (src[(j*w+i)*3+2] * k); // blue
					}
				}
				r = ( r < 0 ? 0 : r);
				g = ( g < 0 ? 0 : g);
				b = ( b < 0 ? 0 : b);
				dst.setPixel(x, y, (((r) << 8) & 0xFF0000) | (g & 0xFF00) | ((b >> 8) & 0xFF));
			}
		}

	// border conditions
	int[][] bc =
			{
			{0, kernel.length, 0, w}, // north with edges
			{h - kernel.length, h, 0, w}, // south with edges
			{kernel.length, h - kernel.length, 0, kernel[0].length}, // west without edges
			{kernel.length, h - kernel.length, w - kernel[0].length ,w} // east without edges
			};
	...
	// same as above (line 7) with condition checks for kx and ky
}
